﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SharpObservation
{
    /// <summary>
    /// Base type for implementing observable objects which are disposable
    /// </summary>
    /// <remarks>
    /// <para>The following example shows how to create an observable class with a name property:</para>
    /// <code>
    /// public class SimpleButObservable : DisposableObservableObject
    /// {
    ///      private string _name;
    ///     
    ///      private static readonly Property&lt;SimpleButObservable, string&gt; NameProperty =
    ///                new Property&lt;SimpleButObservable, string&gt;(
    ///                    c => c.Name,
    ///                    c => c._name,
    ///                    (c, v) => c._name = v);
    ///     
    ///      public string Name
    ///      {
    ///          get { return _name; }
    ///          set { NameProperty.Set(this, value); }
    ///      }
    /// }
    /// </code>
    /// </remarks>
    public abstract class DisposableObservableObject : ObservableObject
          , IIsDisposed
          , IDisposedEvent
    {
        #region IDisposedEvent Members

        /// <summary>
        /// Event Key for managing the Disposing event
        /// </summary>
        internal static readonly EventKey<EventHandler> DisposingEventKey = DisposableEventsObject.DisposingEventKey;

        /// <summary>
        /// Provides notification that this instance is being disposed.
        /// </summary>
        public event EventHandler Disposed
        {
            add    { AddHandler(DisposingEventKey, value); }
            remove { RemoveHandler(DisposingEventKey, value); }
        }

        #endregion


        private bool isDisposed;
        private Action throwIfDisposed = () => { };

        /// <summary>
        ///   Gets whether the factory instance has been disposed.
        /// </summary>
        public bool IsDisposed { get { return isDisposed; } }

        /// <summary>
        ///   Checks whether the factory instance has been disposed, and throws an ObjectDisposedException if it has
        /// </summary>
        /// <exception cref = "ObjectDisposedException">Thrown if instance has been disposed</exception>
        protected Action ThrowIfDisposed { get { return throwIfDisposed; } }

        /// <summary>
        /// Releases resources
        /// </summary>
        /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
        protected virtual void Dispose(bool disposing)
        {
            // this method could be abstract, but is deliberately implemented to support refactoring...
            // derived classes should always call base.Dispose.
        }

        /// <summary>
        ///   Disposes the factory instance
        /// </summary>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly")]
        public void Dispose()
        {
            DisposeHelper.DisposeOf(this, true);
        }

        ///// <summary>
        /////   Finalizes the factory instance. Should never be called.
        ///// </summary>
        //[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly")]
        //~DisposableObject()
        //{
        //    DisposeHelper.DisposeOf(this, false);
        //}

    }
}
